import { useState, useEffect, useRef } from "react";
import { Button, Select } from "@douyinfe/semi-ui";
import { IconCamera } from "@douyinfe/semi-icons";
const Option = Select.Option;

const filterOptions: { name: string; value: string }[] = [
  { name: "None", value: "none" },
  { name: "Blur", value: "blur-sm" },
  { name: "Grayscale", value: "grayscale" },
  { name: "Invert", value: "invert" },
  { name: "sepia", value: "sepia" },
];

const MediaStream = () => {
  const videoRef = useRef<HTMLVideoElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);

  const [audioInputs, setAudioInputs] = useState<MediaDeviceInfo[]>([]);
  const [audioOutputs, setAudioOutputs] = useState<MediaDeviceInfo[]>([]);
  const [videoInputs, setVideoInputs] = useState<MediaDeviceInfo[]>([]);

  const [currentVideoDeviceId, setCurrentVideoDeviceId] = useState<any>();
  const [filter, setFilter] = useState<string>();

  const [setting, setSetting] = useState("");

  useEffect(() => {
    let ms: MediaStream | null = null;
    navigator.mediaDevices
      .getUserMedia({
        video: {
          width: 640,
          height: 480,
          frameRate: 30,
          deviceId: currentVideoDeviceId ? { exact: currentVideoDeviceId } : undefined,
        },
        audio: false,
      })
      .then((mediaStream) => {
        ms = mediaStream;
        if (videoRef.current) {
          videoRef.current.srcObject = mediaStream;
        }

        const videoTrack = mediaStream.getVideoTracks()[0];
        const videoSettings = videoTrack.getSettings();
        const settingJson = JSON.stringify(videoSettings, null, 2);
        setSetting(settingJson);
      })
      .catch((err) => {
        console.log(err);
      });
    return () => {
      // 清理副作用，解除 mediaStream 的 track 播放
      ms &&
        ms.getTracks().forEach((track) => {
          track.stop();
        });
    };
  }, [currentVideoDeviceId]);
  useEffect(() => {
    navigator.mediaDevices
      .enumerateDevices()
      .then((devices) => {
        const ainArr: MediaDeviceInfo[] = [];
        const aoutArr: MediaDeviceInfo[] = [];
        const vinArr: MediaDeviceInfo[] = [];
        devices.forEach((deviceInfo) => {
          switch (deviceInfo.kind) {
            case "audioinput":
              ainArr.push(deviceInfo);
              break;
            case "audiooutput":
              aoutArr.push(deviceInfo);
              break;
            case "videoinput":
              vinArr.push(deviceInfo);
              break;
            default:
              break;
          }
        });
        setAudioInputs(ainArr);
        setAudioOutputs(aoutArr);
        setVideoInputs(vinArr);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  const snapshot = () => {
    if (!canvasRef.current || !videoRef.current) return;
    const ctx = canvasRef.current.getContext("2d");
    if (!ctx) return;
    ctx.drawImage(videoRef.current, 0, 0, canvasRef.current.width, canvasRef.current.height);
  };
  return (
    <div className="flex flex-col items-center">
      <div className="mx-auto flex justify-between mt-6">
        <div>
          <span>Audio input:</span>
          <Select style={{ width: 120 }}>
            {audioInputs.map((item) => (
              <Option value={item.deviceId} key={item.deviceId}>
                {item.label}
              </Option>
            ))}
          </Select>
        </div>
        <div>
          <span>Audio output:</span>
          <Select style={{ width: 120 }}>
            {audioOutputs.map((item) => (
              <Option value={item.deviceId} key={item.deviceId}>
                {item.label}
              </Option>
            ))}
          </Select>
        </div>
        <div>
          <span>Video input:</span>
          <Select
            style={{ width: 120 }}
            onChange={(value) => {
              setCurrentVideoDeviceId(value);
            }}
          >
            {videoInputs.map((item) => (
              <Option value={item.deviceId} key={item.deviceId}>
                {item.label}
              </Option>
            ))}
          </Select>
        </div>
      </div>
      <div>
        <label>Filter 特效</label>
        <Select
          style={{ width: 120 }}
          onChange={(value) => {
            setFilter(value + "");
          }}
        >
          {filterOptions.map((item) => (
            <Option value={item.value} key={item.name}>
              {item.name}
            </Option>
          ))}
        </Select>
      </div>
      <div>{setting}</div>
      <video className={filter} autoPlay playsInline ref={videoRef}></video>
      <div className="w-96 mt-6">
        <Button onClick={snapshot} theme="solid" type="danger" size="large" icon={<IconCamera />}>
          拍摄
        </Button>
      </div>
      <div className="mt-6">
        <canvas width={320} height={240} ref={canvasRef}></canvas>
      </div>
    </div>
  );
};

export default MediaStream;
